/* eslint-disable */

import axios from 'axios'
import isEqual from 'lodash/isEqual'
import {
  pendingRequest,
  refreshCookieData,
  handleError
} from './util'

const { CancelToken } = axios

// 请求拦截，添加请求医院信息
export function requestHosiptalSoid (config, user) {
  if (config.options) {
    const { isAddHospitalSoid, isAddSoid } = config.options
    config.data = config.data || {}
    if (isAddHospitalSoid || isAddSoid) {
      config.data.hospitalSOID = user.hospitalSOID
    }
  }
  return config
}

// 请求拦截，添加请求头信息
export function requestHeader (config, headerData = {}) {
  // 添加系统参数
  config.headers.common = Object.assign(config.headers.common, headerData)
  return config
}

// 请求拦截，防止重复请求
export function requestCancel (config) {
  const { options } = config
  // 添加pending
  function setPendingRequest (url, cancelFn) {
    config.storeUrl = url
    pendingRequest.set(url, {
      cancelFn,
      data: config.data,
      global: options.global || false
    })
  }
  config.cancelToken = new CancelToken(cancelFn => {
    const target = pendingRequest.get(config.url)
    /* url非重复情况 */
    if (!target) {
      setPendingRequest(config.url, cancelFn)
      return config
    }
    /* url重复 */
    // 覆盖之前的请求
    if (options.cover) {
      target.cancelFn('')
      setPendingRequest(config.url, cancelFn)
      return config
    }
    // 允许重复
    if (options.repeat) {
      const repeatList = Array.from(pendingRequest.keys()).filter(url => {
        return url.indexOf(config.url) !== -1
      })
      setPendingRequest(`repeat_${repeatList.length}:${config.url}`, cancelFn)
      return config
    }
    // 不允许重复则取消该请求
    if (isEqual(target.data, config.data)) {
      cancelFn({
        config,
        message: '请求重复',
        url: config.url,
        stack: `请求重复，入参：${JSON.stringify(config.data)}`
      })
    }
  })
  return config
}

// 转换request data
export function requestTransform (config) {
  const { options: { transformData } } = config
  if (transformData) {
    config.data = transformData(config.data)
  }
  return config
}

// check 接口入参data是否合法
export function requestCheckData (config) {
  const { options: { checkFn } } = config
  const message = checkFn ? (checkFn(config.data)) : null
  // 不通过 则取消该请求
  if (message) {
    const target = pendingRequest.get(config.storeUrl || config.url)
    if (target) {
      target.cancelFn({
        config,
        message
      })
    }
  }
  return config
}

// 请求拦截
export const requestInterceptor = (service) => {
  service.interceptors.request.use((config) => {
    const { header, user } = refreshCookieData()
    // 统一添加请求头
    config = requestHeader(config, header)
    // 处理统一添加集团医院ID
    config = requestHosiptalSoid(config, user)
    // 添加修改接口入参 data 的fn
    config = requestTransform(config)
    // 处理借口重复问题
    config = requestCancel(config)
    // 检查数据是否合法
    config = requestCheckData(config)
    return config
  })
}

// 响应拦截
export const responseInterceptor = (service) => {
  service.interceptors.response.use((res) => {
    const { config } = res
    pendingRequest.delete(config.storeUrl)
    return res.data
  }, (err) => {
    // 判断请求是否被取消
    if (axios.isCancel(err)) {
      err = err.message
    }
    const { config } = err
    // 删除pendingRequest 中的存储
    if (config && pendingRequest.has(config.storeUrl)) {
      pendingRequest.delete(config.storeUrl)
    }
    handleError(err)
    // eslint-disable-next-line prefer-promise-reject-errors
    return Promise.reject({
      success: false,
      errorDetail: {
        path: config ? config.url : (err.url || ''),
        detailMsg: err.stack,
        message: err.message
      }
    })
  })
}
